package com.sunfeng.netty.atguigu2.bio;

import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 实例说明：
 * 1) 使用 BIO 模型编写一个服务器端， 监听 9999 端口， 当有客户端连接时， 就启动一个线程与之通讯。
 * 2) 要求使用线程池机制改善， 可以连接多个客户端.
 * 3) 服务器端可以接收客户端发送的数据(telnet 方式即可)。
 * 问题分析：
 * 1) 每个请求都需要创建一个独立的线程,与对应的客户端进行数据Read,业务处理，数据Write
 * 2) 当并发数较大时， 需要创建大量线程来处理连接， 系统资源占用较大。
 * 3) 建立连接后，如果当前线程暂时没有数据可读，则线程就阻塞在Read操作上，造成线程资源浪费
 * @author sunfeng
 * @date 2021/03/22 10:06
 **/
@Slf4j
public class BIOServer {
    public static void main(String[] args) throws IOException {
        //线程池机制
        //思路
        //1. 创建一个线程池
        //2. 如果有客户端连接， 就创建一个线程， 与之通讯(单独写一个方法)
        ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();


        ServerSocket serverSocket = new ServerSocket(9999);
        log.info("服务器开始启动");
        while (true){
            log.info("当前线程名字为:{}当前线程的id为:{}",Thread.currentThread().getName(),Thread.currentThread().getId());
            log.info("等待客户端连接");
            Socket socket = serverSocket.accept();
            log.info("获取到socket{}",socket);
            log.info("连接到一个客户端");
            newCachedThreadPool.execute(()->{
                //可以和客户端通讯
                handler(socket);
            });
        }

    }

    private static void handler(Socket socket) {
        try {
            log.info("当前线程名字为:{},当前线程的id为:{}",Thread.currentThread().getName(),Thread.currentThread().getId());
           byte[] bytes= new byte[1024];
            InputStream inputStream = socket.getInputStream();


            while (true){
                log.info("当前线程名字为:{},当前线程的id为:{}",Thread.currentThread().getName(),Thread.currentThread().getId());
                log.info("读取");
                int read = inputStream.read(bytes);
                log.info("读取成功");
                if(read!=-1){
                    log.info(new String(bytes,0,read));

                }else{
                    break;
                }
            }

        }catch (Exception e){
             e.printStackTrace();
        }finally {
            log.info("关闭和 client 的连接");
            try {
                socket.close();
            }catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
